from fastapi import APIRouter, Depends, Body, Path, UploadFile, File, Header, Query
import typing as T
import logging

from ...pojo.vo import Result
from ...pojo.dto import (
    KnowledgeHeaderDTO,
    UserKnowledgeBaseDTO,
    EmbeddingSearchParamsDTO,
    UpdateImageInfoDTO,
)
from ..service.impl.UserKnowledgeBaseServiceImpl import UserKnowledgeBaseService

router = APIRouter(prefix="/knowledge", tags=["用户知识库相关功能接口"])


@router.post("", response_model=Result)
async def createKnowledgeBase(
    service: UserKnowledgeBaseService,
    userKnowledgeBaseDTO: T.Annotated[
        UserKnowledgeBaseDTO, Body(description="用户知识库的参数")
    ],
):
    """
    # 创建知识库

    在请求体中必须传递用户的id，知识库名称【可选】

    ## 请求体示例

    ```json
    {
        "userId": 1,
        "alias": "我的知识库"
    }
    ```

    ## 返回示例

    ```json
    {
        "code": 1,
        "data": null,
        "msg": "success"
    }
    ```
    """
    await service.createKnowledgeBase(userKnowledgeBaseDTO)
    return Result.success()


@router.post("/upload", response_model=Result)
async def uplaod(
    service: UserKnowledgeBaseService,
    knowledgeHeader: T.Annotated[
        KnowledgeHeaderDTO, Header(description="知识库的头信息【必填】")
    ],
    file: UploadFile = File(description="接收一个文件, pdf, txt, docx, png, jpeg, jpg"),
):
    """
    # 文件上传到知识库

    将文件解析到知识库
    **必须在请求头中传递用户id和知识库id**

    ## 支持的文件类型

    - pdf
    - txt
    - docs
    - csv
    - xlsx
    - png
    - jpg
    - jpeg

    **后续还会再加**

    ## 返回示例
    ```json
    {
        "code": 1,
        "data": null,
        "msg": "success"
    }
    ```
    """
    logging.info(f"接收到文件: {file.filename}")
    data = await service.upload(file, knowledgeHeader)
    return Result.success(data)


@router.get("/search", response_model=Result)
async def search(
    service: UserKnowledgeBaseService,
    embeddingSearchParamsDTO: T.Annotated[
        EmbeddingSearchParamsDTO, Query(description="知识检索的参数")
    ],
    knowledgeBaseId: int = Header(description="知识库id"),
):
    """
    # 知识检索

    根据知识库id和用户输入的文本进行知识检索, 参数以查询参数的形式传递。

    ## 请求示例

    http://localhost:8000/knowledge/search?query=你好&type=image&top_n=1

    ## 返回示例

    ```json
    {
        "code: 1,
        "msg": "success",
        "data": [
            {
                "content": "天空湛蓝，云朵稀疏且形态各异。湖面平静，倒映着蓝天和白云，显得格外宁静。湖边有茂密的树木和灌木丛，远处有一座小桥横跨在湖面上，景色优美。",
                "type": "image",
                "url": "https://.../xxx.jpg",
            }
        ]
    }
    ```
    """
    embeddingSearchParamsDTO.knowledgeBaseId = knowledgeBaseId
    result = await service.search(embeddingSearchParamsDTO)
    return Result.success(result)


@router.get("/images/{knowledgeBaseId}", response_model=Result)
async def getImages(
    server: UserKnowledgeBaseService,
    knowledgeBaseId: T.Annotated[int, Path(description="知识库id")],
    count: T.Annotated[
        int, Query(description="要返回的图片信息的数量【默认-1，表示全返回】")
    ] = -1,
):
    """
    # 获取知识库图片信息列表

    根据知识库id获取知识库的图片信息列表

    ## 返回示例

    ```json
    {
      "code": 1,
      "msg": "success",
      "data": [
                {
                  "url": "https://.../xxx.jpeg",
                  "id": "4994b566-aeb8-46d9-996d-bed4b72e9915",
                  "fileName": "封面.jpg",
                  "content": "天空湛蓝，云朵稀疏且形态各异。湖面平静，倒映着蓝天和白云，显得格外宁静。湖边有茂密的树木和灌木丛，远处有一座小桥横跨在湖面上，景色优美。"
                }
            ]
    }
    ```
    """
    result = await server.getImages(knowledgeBaseId, count)
    return Result.success(result)


@router.get("/{userId}", response_model=Result)
async def getKnowledgeBaseListByUserId(
    service: UserKnowledgeBaseService,
    userId: T.Annotated[int, Path(description="用户id")],
):
    """
    # 获取知识库列表

    根据用户的id获取用户的知识库列表

    ## 返回示例

    ```json
    {
        "code": 1,
        "msg": "success",
        "data": [
            {
                "id": 1,
                "alias": "我的知识库1",
                "userId": 1,
                "createTime": "2023-07-07T08:08:08.000+00:00",
            },
            {
                "id": 2,
                "alias": "我的知识库2",
                "userId": 1,
                "createTime": "2023-07-07T08:08:08.000+00:00",
            }
        ]
    }

    ```
    """
    result = await service.getKnowledgeBaseListByUserId(userId)
    return Result.success(result)


@router.put("", response_model=Result)
async def updateKnowledgeBaseNameByKnowledgeBaseId(
    service: UserKnowledgeBaseService,
    knowledgeBaseId: int = Body(description="知识库id"),
    name: str = Body(description="要更改的知识库名称"),
):
    """
    # 修改知识库名称

    根据知识库id修改知识库名称

    ## 请求体示例

    ```json
    {
        "knowledgeBaseId": 1,
        "name": "知识库改名"
    }
    ```

    ## 返回示例

    ```json
    {
        "code": 1,
        "data": null,
        "msg": "success"
    }
    ```
    """
    await service.updateKnowledgeBaseNameByKnowledgeBaseId(knowledgeBaseId, name)
    return Result.success()


@router.put("/image", response_model=Result)
async def updateImageInfo(
    service: UserKnowledgeBaseService,
    imageInfo: T.Annotated[UpdateImageInfoDTO, Body(description="更改图片信息请求体")],
):
    """
    # 更改图片信息

    根据图片id和知识库id来更新图片描述信息

    ## 请求体示例

    ```json
    {
        "id": "4994b566-aeb8-46d9-996d-bed4b72e9915",
        "knowledgeBaseId": 1,
        "content": "这是修改后的图片描述"
    }
    ```

    ## 返回示例

    ```json
    {
        "code": 1,
        "data": null,
        "msg": "success"
    }
    ```
    """
    await service.updateImageInfo(imageInfo)
    return Result.success()


@router.delete("/{knowledgeBaseId}", response_model=Result)
async def deleteKnowledgeBaseById(
    service: UserKnowledgeBaseService,
    knowledgeBaseId: T.Annotated[int, Path(description="知识库id")],
):
    """
    # 删除知识库

    根据知识库id删除知识库

    ## 返回示例

    ```json
    {
        "code": 1,
        "data": null,
        "msg": "success"
    }

    """
    await service.deleteKnowledgeBaseByKnowledgeId(knowledgeBaseId)
    return Result.success()
